import { GridForm } from "@coldcloude/kakera";
import { ACT_TURN_END, AT_CITY, calcPopularCost, CivSimAction, CivSimActionMulti, CivSimActionPopularAlloc, CivSimActionPopularUnallocCity, CivSimAgent, CivSimArea, CivSimCity, CivSimCivDetail, CivSimObserver, CivSimView } from "./CivSimCommon";
import { CSC } from "./CivSimConstant";
import { KNumTree } from "@coldcloude/kai2";

export class CivSimDisplay implements CivSimObserver {
    ids:number[];
    gridForm:GridForm;
    constructor(ids:number[]){
        this.ids = ids;
    }
    getObservedIds():number[]{
        return this.ids;
    }
    setGridForm(gridForm: GridForm): void {
        this.gridForm = gridForm;
    }
    updateViews(views: CivSimView[]):Promise<void>{
        return new Promise((cb)=>{
            cb();
        });
    }
}

export class CivSimPlayerConfig {

}

export class CivSimPlayer implements CivSimAgent,CivSimObserver {
    cid:number;
    config:CivSimPlayerConfig;
    gridForm:GridForm;
    view:CivSimView;
    civ:CivSimCivDetail;
    commands:number[];
    constructor(cid:number,config:CivSimPlayerConfig){
        this.cid = cid;
        this.config = config;
    }
    _assert(){
        return !!this.gridForm&&!!this.civ;
    }
    getControlId(): number {
        return this.cid;
    }
    _selectPopularAction():CivSimAction{
        let ra:CivSimActionMulti = null;
        const assertRA = ()=>{
            if(!ra){
                ra = new CivSimActionMulti();
            }
            return ra;
        }
        const cityMap = new KNumTree<CivSimCity[]>();
        this.civ.cityMap.foreach((pos,city)=>{
            if(city.level<0){
                //新建城市的人口要用来建城
                if(!city.workerFrom){
                    const a1 = new CivSimActionPopularUnallocCity(pos);
                    assertRA().actions.push(a1);
                    const a2 = new CivSimActionPopularAlloc(pos,pos);
                    assertRA().actions.push(a2);
                }
            }
            else{
                //城市按等级倒序排列
                cityMap.computeIfAbsent(-city.level,()=>[]).push(city);
            }
        });
        cityMap.foreach((lv,cities)=>{
            let found = false;
            for(const city of cities){
                const pos = city.position
                const nps = this.gridForm.getAreaGrids(pos,CSC.city.civilingRadius);
                const workingAreas:CivSimArea[] = [];
                let idleAreas:CivSimArea[] = [];
                for(const np of nps){
                    const area = this.civ.areaMap.get(np);
                    if(area&&(area.sameAs(city)||area.type!==AT_CITY)){
                        if(!area.workerFrom){
                            idleAreas.push(area);
                        }
                        else if(area.workerFrom.sameAs(city)){
                            workingAreas.push(area);
                        }
                    }
                }
                let popCost = 0;
                for(const a of workingAreas){
                    popCost += calcPopularCost(a);
                }
                const popRest = city.popular-popCost;
                while(idleAreas.length>0){
                    const newIdles:CivSimArea[] = [];
                    for(const a of idleAreas){
                        const c = calcPopularCost(a);
                        if(c<=popRest){
                            newIdles.push(a);
                        }
                    }
                    // TODO: random according to config
                    if(newIdles.length>0){
                        const aa = newIdles.pop();
                        assertRA().actions.push(new CivSimActionPopularAlloc(city.position,aa.position));
                        found = true;
                    }
                    idleAreas = newIdles;
                }
            }
            if(found){
                return true;
            }
        });
        return ra;
    }
    _selectAreaAction():CivSimAction{
        let ra = null;
        return ra;
    }
    _selectArmyAction():CivSimAction{
        let ra = null;
        return ra;
    }
    requestAction(): Promise<CivSimAction> {
        return new Promise(cb=>{
            if(!this._assert()){
                cb(null);
            }
            else{
                let action = ACT_TURN_END;
                let a = this._selectPopularAction();
                if(a){
                    action = a;
                }
                else{
                    a = this._selectAreaAction();
                    if(a){
                        action = a;
                    }
                    else{
                        a = this._selectArmyAction();
                        if(a){
                            action = a;
                        }
                    }
                }
                cb(action);
            }
        });
    }
    updateCommands(commands: number[]): Promise<void> {
        return new Promise((cb)=>{
            this.commands = commands;
            cb();
        });
    }
    setGridForm(gridForm: GridForm): void {
        this.gridForm = gridForm;
    }
    getObservedIds(): number[] {
        return [this.cid];
    }
    updateViews(views: CivSimView[]): Promise<void> {
        return new Promise((cb)=>{
            this.view = views[0];
            this.civ = this.view.controlCivs[0];
            cb();
        });
    }
}
